package com.huice;

import org.apache.commons.codec.digest.DigestUtils;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;

public class HttpURLConnectionUtil {

    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    /**
     * Http post请求
     *
     * @param httpUrl     连接
     * @param bodyStr     参数
     * @param contentType 报文类型
     * @return result 响应结果
     */
    public static String doPost(String httpUrl, String bodyStr, String contentType) {
        StringBuilder result = new StringBuilder();
        //连接
        HttpURLConnection connection = null;
        OutputStream os = null;
        InputStream is = null;
        BufferedReader br = null;
        try {
            //创建连接对象
            URL url = new URL(httpUrl);
            //创建连接
            connection = (HttpURLConnection) url.openConnection();
            //设置请求方法
            connection.setRequestMethod("POST");
            //设置连接超时时间
            connection.setConnectTimeout(10000);
            //设置读取超时时间
            connection.setReadTimeout(10000);
            //DoOutput设置是否向httpUrlConnection输出，DoInput设置是否从httpUrlConnection读入，此外发送post请求必须设置这两个
            connection.setDoOutput(true);
            connection.setDoInput(true);
            //设置通用的请求属性
            connection.setRequestProperty("Content-Type", contentType);
            connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
            // Post 请求不能使用缓存
            connection.setUseCaches(false);
            //发送请求
            if (null != bodyStr && !bodyStr.equals("")) {
                //获取写出流
                os = connection.getOutputStream();
                //写入请求参数
                os.write(bodyStr.getBytes(StandardCharsets.UTF_8));
                //推送数据
                os.flush();
            }
            //读取响应
            if (connection.getResponseCode() == 200) {
                is = connection.getInputStream();
            } else {
                is = connection.getErrorStream();
            }
            if (null != is) {
                br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
                String temp;
                while (null != (temp = br.readLine())) {
                    result.append(temp);
                    result.append("\r\n");
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭连接
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            //关闭连接
            if (connection != null) {
                connection.disconnect();
            }
        }
        return result.toString();
    }

    /**
     * 获得排序后的参数坐标
     *
     * @param params 参数
     */
    private static String[] sortParamKeyArray(Map<String, Object> params) {
        String[] keyArray = new String[params.size()];
        int index = 0;
        for (String key : params.keySet()) {
            keyArray[index] = key;
            index++;
        }
        Arrays.sort(keyArray);
        return keyArray;
    }

    /**
     * 构建签名
     *
     * @param appSecret 密钥
     * @param params    参数
     * @param content   报文
     * @return sign 签名
     */
    public static String makeSign(String appSecret, Map<String, Object> params, String content, boolean rejectEmptyCharacters) {
        StringBuilder sign = new StringBuilder();
        sign.append(appSecret);
        //参数排序,适配PHP的ksort()函数
        String[] keys = sortParamKeyArray(params);
        //拼接参数
        for (String key : keys) {
            if (!"sign".equalsIgnoreCase(key) && null != params.get(key)) {
                sign.append(key);
                sign.append(params.get(key));
            }
        }
        sign.append(content);
        sign.append(appSecret);
        String signStr = sign.toString();
        if (rejectEmptyCharacters) {
            signStr = sign.toString().replaceAll("\\s*", "");
        }
        return DigestUtils.md5Hex(signStr).toUpperCase(Locale.ROOT);
    }

    /**
     * 构建URL参数
     *
     * @param params 参数
     */
    public static String makeURLParam(Map<String, Object> params) {
        StringBuilder urlParams = new StringBuilder();
        //拼接参数
        for (Map.Entry<String, Object> entry : params.entrySet()) {
            if (null != params.get(entry.getKey())) {
                urlParams.append("&");
                urlParams.append(entry.getKey());
                urlParams.append("=");
                if ("timestamp".equalsIgnoreCase(entry.getKey())) {
                    String timestamp = String.valueOf(entry.getValue());
                    urlParams.append(timestamp.replace(" ", "%20"));
                    continue;
                }
                urlParams.append(entry.getValue());

            }
        }
        return urlParams.substring(1);
    }

    /**
     * ERP推送接口使用示例
     */
    public static String erpAPI(String httpUrl, String method, String appKey, String appSecret, String sid, String content) {
        Map<String, Object> params = new HashMap<>();
        params.put("method", method);
        params.put("timestamp", sdf.format(new Date()));
        params.put("format", "xml");
        params.put("appkey", appKey);
        params.put("sign_method", "md5");
        params.put("sid", sid);
        params.put("sign", makeSign(appSecret, params, content, true));

        httpUrl += "?" + makeURLParam(params);
        System.out.println("请求地址参数：" + httpUrl);
        String message = doPost(httpUrl, content, "text/xml;charset=utf-8");
        System.out.println("响应结果：" + message);
        return message;
    }

    public static void main(String[] args) {
        //ERP 推单
        String httpUrl = "http://39.105.14.222/wms_api/wdt_service.php";
        String method = "WDT_WMS_DELIVERYORDER_CREATE";
        String appKey = "以实际联调人员分配为准";
        String appSecret = "以实际联调人员分配为准";
        String sid = "以实际联调人员分配为准";
        // content 用实际接口的入参报文替代
        String content = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><request><deliveryOrder><deliveryOrderCode>postman_166260538551054698</deliveryOrderCode><orderType>JYCK</orderType><warehouseCode>warehouse_sly</warehouseCode><sourcePlatformCode>TM</sourcePlatformCode><sourcePlatformName></sourcePlatformName><logisticsCode>SFHH-XX</logisticsCode><createTime>2018-10-18 13:48:52</createTime><placeOrderTime>2018-10-18 13:47:25</placeOrderTime><payTime>2018-10-18 13:47:25</payTime><operateTime>2018-10-18 13:48:52</operateTime><shopNick>postman店铺</shopNick><buyerNick>买家</buyerNick><totalAmount>120</totalAmount><gotAmount>0</gotAmount><arAmount>100</arAmount><freight>0</freight><logisticsAreaCode>标准大头笔</logisticsAreaCode><invoiceFlag>N</invoiceFlag><buyerMessage/><serviceFee>110</serviceFee><sellerMessage>客服备注</sellerMessage><printRemark>打印备注</printRemark><senderInfo><name>1</name><mobile>1</mobile><province>天津市</province><city>天津市</city><area>滨海新区</area><detailAddress>华夏金融大厦</detailAddress></senderInfo><receiverInfo><name>倚天剑</name><idType>1</idType><idNumber>12344</idNumber><mobile> 13789888477 </mobile><tel></tel><province>河北省</province><city>邯郸市</city><area>邯山区</area><zipCode/><detailAddress>邯郸科技职业学院</detailAddress></receiverInfo><invoices><invoice><type>INVOICE</type><header>嘉兴河海中控信息</header><amount>868</amount><content>内容</content><taxNumber>我是税号</taxNumber></invoice></invoices><insurance><type>保险类型</type><amount>01</amount></insurance><deliveryRequirements><deliveryType>PTPS</deliveryType></deliveryRequirements><extendProps><flag_id>10</flag_id><wdtfx_platform>YZ</wdtfx_platform></extendProps></deliveryOrder><orderLines><orderLine><orderLineNo>1</orderLineNo><ownerCode>sly</ownerCode><itemCode>iphone</itemCode><itemId>409</itemId><inventoryType>ZP</inventoryType><itemName></itemName><sourceOrderCode>postman_166260538551054698</sourceOrderCode><subSourceOrderCode></subSourceOrderCode><payNo>payNo2</payNo><planQty>3</planQty><batchCode></batchCode><actualPrice>50</actualPrice><discountAmount>01</discountAmount><retailPrice>100</retailPrice><extendProps><erpDiscountRatio>0</erpDiscountRatio><fromMask>0</fromMask><suiteName>组合装</suiteName><suiteNum>1</suiteNum><payAccount>payAccount1</payAccount></extendProps><remark>备注</remark></orderLine></orderLines><extendProps><ConsolidationCode>集包地编码</ConsolidationCode><ConsolidationName>集包地名字，这个是可以打印的</ConsolidationName></extendProps></request>";
        String message = erpAPI(httpUrl, method, appKey, appSecret, sid, content);
        assert !"".equals(message);
    }
}
